import sys
import PySimpleGUI as sg
import subprocess
from pathlib import Path
import xml.etree.ElementTree as et

# 修复高DPI感知
if sys.platform == 'win32':
    try:
        import ctypes

        ctypes.OleDLL('shcore').SetProcessDpiAwareness(1)
    except (ImportError, AttributeError, OSError):
        pass

class App:
    def __init__(self, name, xml_path, is_installed):
        self.name = name
        self.xml_path = xml_path
        self.is_installed = is_installed


def install(app):
    regcmd = f'Add-AppxPackage -DisableDevelopmentMode -Register "{app.xml_path}"'
    # print(regcmd)
    try:
        subprocess.run(["powershell", "-Command", regcmd])
        app.is_installed = True
        print(f'{app.name} 安装成功')
        window[app.name].update(text_color='grey')
        # window[app.app_name].update(disabled=True)
        window[f"installbt-{app.name}"].update(disabled=True, button_color='grey')
    except:
        print(f'{app.name} 安装失败')


def uninstall(app):
    unregcmd = f"Get-AppxPackage -Name '*{app.name}*' | Remove-AppxPackage"
    try:
        result = subprocess.run(["powershell", "-Command", unregcmd], capture_output=True, text=True)
        if result.returncode == 0:
            print("卸载命令执行成功！")
        else:
            print('命令执行失败，参考：')
            print(result.stdout)
            print(result.stderr)
        if notfoundAppx(app.name):
            print(app.name, '确认已卸载!')
            app.is_installed = False
            window[app.name].update(text_color='red')
            window[f"installbt-{app.name}"].update(disabled=False, button_color='#ff9900')
        else:
            print('应用还存在，似乎未卸载成功')

    except:
        print(f'{app.name} 卸载失败')


def getColor(app):
    if app.is_installed:
        return 'grey'
    else:
        return 'red'


def getBtColor(app):
    if app.is_installed:
        return 'grey'
    else:
        return '#ff9900'


def getDisabled(app):
    if app.is_installed:
        return True
    else:
        return False


def notfoundAppx(app_name):  # 检查指定的应用程序是否不存在
    # 定义一个命令，用于搜索指定应用程序
    command = f"Get-AppxPackage -Name '*{app_name}*'"
    try:
        # 使用PowerShell运行命令，并将输出捕获到check_result中
        check_result = subprocess.run(["powershell", command], capture_output=True, text=True)
        # 如果输出为空，则表示应用程序不存在
        if check_result.stdout.strip() == "":
            return True
        else:
            return False
    except Exception as e:
        # 如果出现异常，则打印异常信息
        print(f"An error occurred: {e}")


cmd = 'Get-AppxPackage | Select-Object -ExpandProperty Name'
echo = subprocess.check_output(["powershell", "-Command", cmd]).decode('utf-8')
path = Path("C:/Program Files/WindowsApps/")
app_folder = [folder for folder in path.iterdir() if
              folder.is_dir() and '.' in folder.name and 'neutral' not in folder.name]
apps = {}
for x in app_folder:
    xml_file = x / 'AppxManifest.xml'
    # print(x.name)
    # print(xml_file)
    root = et.parse(xml_file).getroot()
    namespace = root.tag.split('}')[0] + "}"
    appname = root.find(f"{namespace}Identity").get("Name").strip()
    # print(appname)
    if appname is not None:
        app = App(appname, xml_file, True)
        if appname not in echo:
            app.is_installed = False
        apps[appname] = app
# for x in apps:
#     print(x.app_name, x.is_installed)

sg.set_options(font=('微软雅黑', 8))
sg.theme('SystemDefaultForReal')
row_cap = 4 if len(apps) > 33 else 3
frame_layout = []
row_layout = []

for index, app in enumerate(apps.values()):
    if index % row_cap == 0:
        row_layout = []

    column_layout = [[
        sg.Checkbox(app.name, size=(34, 1), key=app.name, text_color=getColor(app)),
        sg.Button('安装', key=f'installbt-{app.name}', disabled=getDisabled(app), button_color=getBtColor(app)),
        sg.Button('卸载', key=f'uninstallbt-{app.name}')
    ]]
    row_layout.append(sg.Column(column_layout))
    if len(row_layout) == row_cap or index == len(apps) - 1:
        frame_layout.append(row_layout)
layout = [
    [sg.Frame('预装应用列表', frame_layout)],
    [
        sg.Button('全选'),
        sg.Button('反选'),
        sg.Button('全不选'),
        sg.Button('选择未安装'),
        sg.Button('一键安装'),
        sg.Button('一键卸载'),
        sg.Button('输出信息'),
        sg.Button('输出名称')
    ]
]

window = sg.Window('恢复预装应用', layout)

while True:
    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Cancel'):
        break

    if event.startswith('installbt-'):
        app_name = event.split('bt-')[1]
        install(apps[app_name])

    if event.startswith('uninstallbt-'):
        app_name = event.split('bt-')[1]
        uninstall(apps[app_name])

    if event == '全选':
        for app in apps.values():
            window[f'{app.name}'].update(True)
    elif event == '反选':
        for app in apps.values():
            window[app.name].update(not window[app.name].get())
    elif event == '全不选':
        for app in apps.values():
            window[app.name].update(False)
    elif event == '选择未安装':
        for app in apps.values():
            window[app.name].update(not app.is_installed)
    elif event == '一键安装':
        selected_apps = [app for app in apps.values() if window[app.name].get()]
        if sg.popup_yes_no(f'确定要安装选中的{len(selected_apps)}个应用吗?') == 'Yes':
            for app in selected_apps:
                install(app)
            sg.popup('应用安装完成！')
    elif event == '一键卸载':
        selected_apps = [app for app in apps.values() if window[app.name].get()]
        if sg.popup_yes_no(f'确定要卸载选中的{len(selected_apps)}个应用吗?') == 'Yes':
            for app in selected_apps:
                uninstall(app)
            sg.popup('应用卸载完成！')
    if event == '输出信息':
        selected_apps = [app for app in apps.values() if window[app.name].get()]
        count = 0
        for app in selected_apps:
            count += 1
            print(f'{count} {"=" * 50}\n名称:{app.name}\n文件:{app.xml_path}\n是否安装:{app.is_installed}')
    if event == '输出名称':
        selected_apps = [app for app in apps.values() if window[app.name].get()]
        print('\n'.join([app.name for app in selected_apps]))
window.close()